﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WH.Common.Config;
using WH.Common.Helper;

namespace WH.Services.Middleware
{
    public class ContextHandlerMiddleware
    {

        private readonly RequestDelegate _next;
        private readonly ILogger<ContextHandlerMiddleware> _logger;
        private readonly IConfigurationCenter _configurationCenter;

        /// <summary>
        /// 计时器
        /// </summary>
        private Stopwatch _stopwatch;
        //加密解密key
        private readonly string securitykey = "0123456789abcdef";

        /// <summary>
        /// 忽略加密的方法
        /// </summary>
        public static readonly string[] IgnoreToken = new string[] { "/file/" };


        /// <summary>
        /// 构造 Http 请求中间件
        /// </summary>
        /// <param name="next"></param>
        /// <param name="loggerFactory"></param>
        /// <param name="cacheService"></param>
        public ContextHandlerMiddleware(
            RequestDelegate next,
            ILogger<ContextHandlerMiddleware> loggerFactory,
            IConfigurationCenter configurationCenter)
        {
            _next = next;
            _logger = loggerFactory;
            _configurationCenter = configurationCenter;
        }

        /// <summary>
        /// 1：将Post方法中Body中的数据进行AES解密
        /// 2：将返回数据进行AES加密
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            var reqRespEncryptOptions = _configurationCenter.ReqRespEncryptOptions;

            var header = context.Request.Headers["EnableEncrypt"];

            var isEnableEncrypt = reqRespEncryptOptions.Enable || (string.IsNullOrWhiteSpace(header) == false && header.ToString().Equals(bool.FalseString, StringComparison.OrdinalIgnoreCase) == false);

            if (isEnableEncrypt == false || string.IsNullOrWhiteSpace(context.Request.Headers["Authorization"]))
            {
                await _next(context);
                return;
            }

            var path = context.Request.Path.Value;

            var ign = reqRespEncryptOptions.IgnorePaths.Contains(path, StringComparer.OrdinalIgnoreCase);

            if (ign)
            {
                await _next(context);
                return;
            }

            // 解密请求体
            using (var reader = new StreamReader(context.Request.Body))
            {
                var body = await reader.ReadToEndAsync();
                // 在这里对请求体进行解密操作
                // 例如：body = Decrypt(body);

                var payload = JsonConvert.DeserializeObject<SecurityPayloadDto>(body);

                string bodyStr = string.Empty;

                if (payload is not null)
                {
                    if (!string.IsNullOrWhiteSpace(payload.EncryptPayload))
                    {
                        bodyStr = SecurityHelper.FrontendAesDecrypt(payload.EncryptPayload);
                    }
                }

                context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(bodyStr));
            }

            // 获取url参数
            string param = context.Request.Query["EncryptParam"];
            if (!string.IsNullOrWhiteSpace(param))
            {
                // 解密数据
                string decryptedString = SecurityHelper.FrontendAesDecrypt(param);

                // 更新url参数值
                context.Request.QueryString = new QueryString($"?{decryptedString}");
            }

            // 加密返回体
            using (var originalResponseBody = context.Response.Body)
            {
                using (var memoryStream = new MemoryStream())
                {
                    context.Response.Body = memoryStream;

                    await _next(context);

                    memoryStream.Seek(0, SeekOrigin.Begin);
                    var responseBody = await new StreamReader(memoryStream).ReadToEndAsync();
                    // 在这里对返回体进行加密操作
                    // 例如：responseBody = Encrypt(responseBody);

                    responseBody = SecurityHelper.FrontendAesEncrypt(responseBody);

                    SecurityResponseDto responseDto = new SecurityResponseDto()
                    {
                        EncryptResponse = responseBody
                    };

                    string responseStr = JsonConvert.SerializeObject(responseDto);

                    //memoryStream.Seek(0, SeekOrigin.Begin);

                    // 将加密后的响应写回到响应流中
                    byte[] responseBytes = Encoding.UTF8.GetBytes(responseStr);

                    context.Response.Headers.Remove("Content-Length");
                    context.Response.Headers.Add("Content-Length", new[] { responseBytes.Length.ToString() });
                    context.Response.Headers.Add("EnableEncrypt", isEnableEncrypt.ToString());

                    context.Response.Body.SetLength(0); // 清空原始响应流

                    using (var writer = new StreamWriter(originalResponseBody))
                    {
                        await writer.WriteAsync(responseStr);
                        await writer.FlushAsync();
                    }

                    //await context.Response.Body.WriteAsync(responseBytes, 0, responseBytes.Length);
                    //await context.Response.Body.FlushAsync();

                    //context.Response.Body.Seek(0, SeekOrigin.Begin);

                    //await memoryStream.CopyToAsync(originalResponseBody);
                }
            }

            //context.Request.EnableBuffering();
            //_stopwatch = new Stopwatch();
            //_stopwatch.Start();
            //_logger.LogInformation($"Handling request: " + context.Request.Path);
            //var api = new ApiRequestInputViewModel
            //{
            //    HttpType = context.Request.Method,
            //    Query = context.Request.QueryString.Value ?? "",
            //    Param = context.Request.Query["param"],
            //    RequestUrl = context.Request.Path,
            //    RequestName = "",
            //    RequestIP = context.Request.Host.Value
            //};

            //var request = context.Request.Body;
            //var response = context.Response.Body;

            //try
            //{
            //    using var newRequest = new MemoryStream();
            //    //替换request流
            //    context.Request.Body = newRequest;

            //    using var newResponse = new MemoryStream();
            //    //替换response流
            //    context.Response.Body = newResponse;

            //    using (var reader = new StreamReader(request))
            //    {
            //        //读取原始请求流的内容
            //        api.Body = await reader.ReadToEndAsync();
            //        if (!string.IsNullOrWhiteSpace(api.Body))
            //        {
            //            api.Body = SecurityHelper.FrontendAesDecrypt(api.Body);
            //        }
            //        //示例加密字符串，使用 AES-ECB-PKCS7 方式加密，密钥为：0123456789abcdef
            //        // 加密参数：{"value":"哈哈哈"}
            //        // 加密后数据： oedwSKGyfLX8ADtx2Z8k1Q7+pIoAkdqllaOngP4TvQ4=
            //        //else
            //        //{
            //        //    await _next.Invoke(context);
            //        //}
            //    }

            //    // 获取url参数
            //    string param = context.Request.Query["EncryptParam"];
            //    if (!string.IsNullOrWhiteSpace(param))
            //    {
            //        // 解密数据
            //        string decryptedString = SecurityHelper.FrontendAesDecrypt(param);

            //        // 更新url参数值
            //        context.Request.QueryString = new QueryString($"?{decryptedString}");
            //    }

            //    if (!string.IsNullOrWhiteSpace(api.Body))
            //    {
            //        using var writer = new StreamWriter(newRequest);
            //        await writer.WriteAsync(api.Body);
            //        await writer.FlushAsync();
            //        newRequest.Position = 0;
            //        context.Request.Body = newRequest;
            //    }
            //    await _next.Invoke(context);

            //    using (var reader = new StreamReader(newResponse))
            //    {
            //        newResponse.Position = 0;
            //        api.ResponseBody = await reader.ReadToEndAsync();
            //        if (!string.IsNullOrWhiteSpace(api.ResponseBody))
            //        {
            //            api.ResponseBody = SecurityHelper.FrontendAesEncrypt(api.ResponseBody);
            //        }
            //    }

            //    var dataByte = Encoding.Default.GetBytes(api.ResponseBody);
            //    context.Response.Headers.Remove("Content-Length");
            //    context.Response.Headers.Add("Content-Length", new[] { dataByte.Length.ToString() });
            //    context.Response.Headers.Add("EnableEncrypt", isEnableEncrypt.ToString());

            //    using (var writer = new StreamWriter(response))
            //    {
            //        await writer.WriteAsync(api.ResponseBody);
            //        await writer.FlushAsync();
            //    }
            //}
            //catch (Exception ex)
            //{
            //    _logger.LogError($" http中间件发生错误: " + ex.ToString());
            //}
            //finally
            //{
            //    context.Request.Body = request;
            //    context.Response.Body = response;
            //}

            //// 响应完成时存入缓存
            //context.Response.OnCompleted(() =>
            //{
            //    _stopwatch.Stop();
            //    api.ElapsedTime = _stopwatch.ElapsedMilliseconds;

            //    _logger.LogDebug($"RequestLog:{DateTime.Now.ToString("yyyyMMddHHmmssfff") + new Random().Next(0, 10000)}-{api.ElapsedTime}ms", $"{JsonConvert.SerializeObject(api)}");
            //    return Task.CompletedTask;
            //});

            //_logger.LogDebug($"Finished handling request.{_stopwatch.ElapsedMilliseconds}ms");

            //private readonly RequestDelegate _next;
            //private readonly ILogger _logger;

            ///// <summary>
            ///// 计时器
            ///// </summary>
            //private Stopwatch _stopwatch;
            ////加密解密key
            //private readonly string securitykey = "0123456789abcdef";

            ///// <summary>
            ///// 构造 Http 请求中间件
            ///// </summary>
            ///// <param name="next"></param>
            ///// <param name="loggerFactory"></param>
            ///// <param name="cacheService"></param>
            //public ContextHandlerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
            //{
            //    _next = next;
            //    _logger = loggerFactory.CreateLogger<ContextHandlerMiddleware>();
            //}

            ///// <summary>
            ///// 1：将Post方法中Body中的数据进行AES解密
            ///// 2：将返回数据进行AES加密
            ///// </summary>
            ///// <param name="context"></param>
            ///// <returns></returns>
            //public async Task Invoke(HttpContext context)
            //{





            //    //string method = string.Join(",", IgnoreToken.Select(it => it)).ToLower();
            //    //if (method.Contains(context.Request.Path.Value.ToLower()))
            //    //{
            //    //    await _next(context);
            //    //}

            //    //context.Request.EnableBuffering();

            //    //var api = new ApiRequestInputViewModel
            //    //{
            //    //    HttpType = context.Request.Method,
            //    //    Query = context.Request.QueryString.Value,
            //    //    RequestUrl = context.Request.Path,
            //    //    RequestName = "",
            //    //    RequestIP = context.Request.Host.Value
            //    //};

            //    //var request = context.Request.Body;
            //    //var response = context.Response.Body;
            //    //string error = "";//异常信息
            //    //try
            //    //{
            //    //    using (var newRequest = new MemoryStream())
            //    //    {
            //    //        //替换request流
            //    //        context.Request.Body = newRequest;

            //    //        using (var newResponse = new MemoryStream())
            //    //        {
            //    //            //替换response流
            //    //            context.Response.Body = newResponse;
            //    //            //读取原来的流到新的请求处理
            //    //            using (var reader = new StreamReader(request))
            //    //            {
            //    //                //读取原始请求流的内容
            //    //                api.Body = await reader.ReadToEndAsync();
            //    //                if (!string.IsNullOrWhiteSpace(api.Body))
            //    //                {
            //    //                    //示例加密字符串，使用 AES-ECB-PKCS7 方式加密，密钥为：0123456789abcdef
            //    //                    // 加密参数：{"value":"哈哈哈"}
            //    //                    // 加密后数据： oedwSKGyfLX8ADtx2Z8k1Q7+pIoAkdqllaOngP4TvQ4=
            //    //                    api.Body = SecurityHelper.FrontendAesDecrypt(api.Body);
            //    //                }
            //    //                else
            //    //                {
            //    //                    await _next.Invoke(context);
            //    //                }
            //    //            }
            //    //            if (!string.IsNullOrWhiteSpace(api.Body))
            //    //            {
            //    //                //赋值给原来的流
            //    //                using (var writer = new StreamWriter(newRequest))
            //    //                {
            //    //                    await writer.WriteAsync(api.Body);
            //    //                    await writer.FlushAsync();
            //    //                    newRequest.Position = 0;
            //    //                    context.Request.Body = newRequest;
            //    //                    await _next.Invoke(context);
            //    //                }
            //    //            }
            //    //            //获取原来写回的流
            //    //            using (var reader = new StreamReader(newResponse))
            //    //            {
            //    //                newResponse.Position = 0;
            //    //                api.ResponseBody = await reader.ReadToEndAsync();
            //    //                if (!string.IsNullOrWhiteSpace(api.ResponseBody))
            //    //                {
            //    //                    //api.ResponseBody = api.ResponseBody;
            //    //                    api.ResponseBody = SecurityHelper.FrontendAesEncrypt(api.ResponseBody);
            //    //                }
            //    //            }
            //    //            //将返回的Response流Copy到原始流
            //    //            var dataByte = Encoding.Default.GetBytes(api.ResponseBody);
            //    //            //context.Response.ContentType = "application/ison";
            //    //            context.Response.Headers.Remove("Content-Length");
            //    //            context.Response.Headers.Add("Content-Length", new[] { dataByte.Length.ToString() });
            //    //            //await originalResponsestream.WriteAsync (dataByte,0, dataByte. Length);
            //    //            //context. Response.Body = originalResponsestream 
            //    //            //把处理好的流写回去
            //    //            using (var writer = new StreamWriter(response))
            //    //            {
            //    //                await writer.WriteAsync(api.ResponseBody);
            //    //                await writer.FlushAsync();
            //    //            }
            //    //        }
            //    //    }
            //    //}
            //    //catch (Exception ex)
            //    //{
            //    //    //Console.Write(ex);
            //    //    //error = JsonConvert.SerializeObject(new ReusltEntity
            //    //    //{
            //    //    //    code = "2",
            //    //    //    msg = ex.Message,
            //    //    //    error = ex.StackTrace
            //    //    //});
            //    //}
            //    //finally
            //    //{
            //    //    context.Request.Body = request;
            //    //    context.Response.Body = response;
            //    //    if (!string.IsNullOrEmpty(error))
            //    //    {
            //    //        await context.Response.WriteAsync(error);
            //    //    }
            //    //}
            //    //// 响应完成时存入缓存
            //    //context.Response.OnCompleted(() =>
            //    //{
            //    //    return Task.CompletedTask;
            //    //});
            //}
        }
    }

    public class SecurityPayloadDto
    {
        public string EncryptPayload { get; set; } = null!;
    }

    public class SecurityResponseDto
    {
        public string EncryptResponse { get; set; } = null!;
    }
    internal class ApiRequestInputViewModel
    {
        /// <summary>
        /// 请求接口名称
        /// </summary>
        public string RequestName { get; set; }

        /// <summary>
        /// 请求来源IP
        /// </summary>
        public string RequestIP { get; set; }

        /// <summary>
        /// 请求路径
        /// </summary>
        public string RequestUrl { get; set; }

        /// <summary>
        /// 请求类型：GET/POST
        /// </summary>
        public string HttpType { get; set; }

        /// <summary>
        /// 请求参数字符串
        /// </summary>
        public string Query { get; set; }

        public string Param { get; set; }

        /// <summary>
        /// 请求报文，POST专用
        /// </summary>
        public string Body { get; set; }

        public string RequestTime { get; set; }

        public string ResponseBody { get; set; }

        public long ElapsedTime { get; set; }

        public ApiRequestInputViewModel()
        {
            RequestName = string.Empty;
            RequestIP = string.Empty;
            RequestUrl = string.Empty;
            HttpType = string.Empty;
            Query = string.Empty;
            Param = string.Empty;
            RequestTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
            Body = string.Empty;
            ResponseBody = string.Empty;
            ElapsedTime = -1;
        }

    }
}

